<template>
  <el-dialog
    ref="uploadForm"
    class="upload-dialog"
    :form="form"
    :title="title"
    :visible.sync="visibleDialog"
    :width="width"
    :close-on-press-escape="closeOnPressEscape"
    :close-on-click-modal="closeOnClickModal"
    append-to-body
  >
    <div>
      <el-upload
        v-show="fileList.length < limit"
        ref="upload"
        style="display: inline-block;margin-right: 10px;"
        action=""
        multiple
        :accept="accept"
        :limit="limit"
        :show-file-list="false"
        :on-exceed="handleExceed"
        :auto-upload="true"
        :before-upload="handleBeforeUpload"
        :http-request="handleRequest"
        :file-list="fileList"
      >
        <el-button
          icon="el-icon-search"
          :disabled="fileList.length >= limit"
          type="primary"
        >
          选择文件...
        </el-button>
      </el-upload>
      <!--            <el-button icon="el-icon-upload" type="primary" plain @click="batchUpload">批量上传</el-button>-->
      <!--            <el-button icon="el-icon-delete" type="primary" plain @click="clearUpload">清空上传</el-button>-->
    </div>
    <br />
    <div class="tip">
      当前允许上传文件<b>{{ limit }}</b>个{{ accept ? '，接受的文件格式为' + accept : '' }}，文件最大不能超过<b>{{ bitToKBit(maxSize) }}KB</b>
    </div>
    <el-table
      :data="fileList"
      row-key="uid"
      stripe
    >
      <el-table-column
        prop="name"
        label="文件名"
      >
        <template slot-scope="scope">
          {{ scope.row.file.name }}
        </template>
      </el-table-column>
      <el-table-column
        prop="type"
        label="文件类型"
      >
        <template slot-scope="scope">
          {{ scope.row.file.type }}
        </template>
      </el-table-column>
      <el-table-column
        prop="size"
        label="文件大小"
      >
        <template slot-scope="scope">
          {{ bitToKBit(scope.row.file.size) }}KB
        </template>
      </el-table-column>
      <el-table-column
        label="上传进度"
        prop="percentage"
      >
        <template slot-scope="scope">
          <el-progress
            v-show="scope.row.percentage !== 100"
            :percentage="scope.row.percentage"
          />
          <el-progress
            v-show="scope.row.percentage === 100"
            :percentage="scope.row.percentage"
            status="success"
          />
        </template>
      </el-table-column>
      <el-table-column
        fixed="right"
        label="操作"
      >
        <template slot-scope="scope">
          <el-button
            type="text"
            @click="delFile(scope.$index, scope.row)"
          >
            删除
          </el-button>
          <el-button
            v-if="isImage(scope.row)"
            type="text"
            @click="viewImage(scope.$index, scope.row)"
          >
            查看
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    <div style="text-align: right;margin-top: 40px;">
      <el-button @click="closeDialog">
        关闭
      </el-button>
      <el-button
        type="primary"
        @click="handleConfirm"
      >
        确定
      </el-button>
    </div>
    <el-image-viewer
      v-if="showViewer"
      :on-close="showViewerClose"
      :url-list="[previewUrl]"
    />
  </el-dialog>
</template>

<script>
import Vue from 'vue';
import ElImageViewer from 'element-ui/packages/image/src/image-viewer';
import {cloneJson, parseTime, toast} from "../../utils";
import {uploadImg} from "../../api/file";
import {Button, Dialog, Progress, Table, TableColumn, Upload} from "element-ui";
Vue.use(Upload);
Vue.use(Button);
Vue.use(Table);
Vue.use(TableColumn);
Vue.use(Dialog);
Vue.use(Progress);
/**
 * 文件上传组件
 * @author maolin
 */
export default {
  name: "FileUpload",
  components: {
    ElImageViewer
  },
  props: {
    /**
     * 弹窗标题
     * @public
     */
    title: {
      type: String,
      default: '文件上传'
    },
    /**
     * 弹窗宽度
     * @public
     */
    width: {
      type: String,
      default: '80%'
    },
    /**
     * 是否使用ESC关闭弹窗
     * @public
     */
    closeOnPressEscape: {
      type: Boolean,
      default: false
    },
    /**
     * 是否可通过点击阴影部分关闭弹窗
     * @public
     */
    closeOnClickModal: {
      type: Boolean,
      default: false
    },
    /**
     * 最大上传文件数量
     * @public
     */
    limit: {
      type: Number,
      default: 1
    },
    /**
     * 接受的文件类型
     * @public
     */
    accept: {
      type: String,
      default: 'image/*'
    },
    /**
     * 单个文件可上传的最大大小
     * @public
     */
    maxSize: {
      type: Number,
      default: 2 * 1024 * 1024
    }
  },
  data () {
    return {
      form: null,
      fileList: [],
      showViewer: false,
      previewUrl: null,
      visibleDialog: false,
    };
  },

  computed: {
    bitToKBit () {
      return function (bit) {
        if(bit) {
          return parseInt(bit / 1024);
        }
        return null;
      };
    },
    isImage () {
      return function (row) {
        let imageExt = [
          'jpeg',
          'jpg',
          'png',
          'gif',
          'bmp',
        ];
        let filename = row.file.name;
        let index = filename.lastIndexOf(".");
        let suffix = filename.substr(index+1);
        if (imageExt.indexOf(suffix.toLowerCase()) > -1) {
          return true;
        } else {
          return false;
        }
      };
    }
  },
  methods: {
    /**
     * 显示弹窗
     * @public
     */
    showDialog () {
      this.visibleDialog = true;
    },
    /**
     * 关闭弹窗
     * @public
     */
    closeDialog () {
      this.visibleDialog = false;
    },
    /**
     * 预览图片
     * @public
     */
    viewImage (index, item) {
      this.previewUrl = item.url;
      this.showViewer = true;
    },
    /**
     * 图片上传之前的大小校验
     * @public
     */
    handleBeforeUpload (file) {
      const isLt = file.size < this.maxSize;
      if (!isLt) {
        toast({
          message: '上传文件大小不能超过 ' + this.bitToKBit(this.maxSize) + 'KB!',
          type: 'error'
        });
        return false;
      }
      return true;
    },
    /**
     * 文件超出上传个数时触发
     * @public
     */
    handleExceed(files, fileList) {
      toast({
        message: '文件个数已超出限制',
        type: 'error'
      });
      return false;
    },
    /**
     * 移除文件
     * @public
     */
    delFile (index,item) {
      this.fileList.splice(index, 1);
    },
    /**
     * 文件上传之后请求服务端
     * @public
     */
    handleRequest (data) {
      let file = data.file;

      this.fileList.push({
        file: file,
        percentage: 0,
        uid: file.uid,
      });
      let formdata = new FormData();
      let uid = file.uid;
      let fileList = this.fileList;
      let index = -1;
      for(let i in fileList) {
        if (fileList[i].file.uid === uid) {
          index = i;
          if(fileList[i].percentage === 100) {
            return false;
          }
        }
      }
      formdata.append('file', file);
      const config = {
        onUploadProgress: progressEvent => {
          // progressEvent.loaded:已上传文件大小
          // progressEvent.total:被上传文件的总大小
          this.fileList[index].percentage = Number((progressEvent.loaded / progressEvent.total * 100).toFixed(2));

        }
      };
      uploadImg(formdata, config)
        .then(res => {
          this.fileList[index].url = res.data.path;
        });
    }
    /**
     * 上传之后确认保存值
     * @public
     */
    ,handleConfirm () {
      let flag = false;
      let fileList = cloneJson(this.fileList);
      for (let i in fileList) {
        if(fileList[i].url === undefined || !fileList[i].url) {
          flag = true;
        }
      }
      if(flag) {
        this.$confirm('当前存在未上传的文件, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          this.$emit('save', fileList);
          this.visibleDialog = false;
        }).catch(() => {
        });
      } else {
        this.$emit('save', fileList);
        this.visibleDialog = false;
      }
    },
    /**
     * 关闭图片预览
     * @public
     */
    showViewerClose () {
      this.showViewer = false;
    }
  }
};
</script>

<style lang="scss" scoped>
    .upload-dialog{
        text-align: left;
    }
</style>
